// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Net;
using System.Text;
using MQTTnet.Diagnostics.Logger;
using MQTTnet.Internal;
using MQTTnet.Protocol;

namespace MQTTnet.TestApp;

public static class ClientTest
{
    public static async Task RunAsync()
    {
        try
        {
            var logger = new MqttNetEventLogger();
            MqttNetConsoleLogger.ForwardToConsole(logger);

            var factory = new MqttClientFactory(logger);
            var client = factory.CreateMqttClient();
            var clientOptions = new MqttClientOptions
            {
                ChannelOptions = new MqttClientTcpOptions
                {
                    RemoteEndpoint = new DnsEndPoint("127.0.0.1", 0)
                }
            };

            client.ApplicationMessageReceivedAsync += e =>
            {
                var payloadText = string.Empty;
                if (e.ApplicationMessage.Payload.Length > 0)
                {
                    payloadText = Encoding.UTF8.GetString(e.ApplicationMessage.Payload);
                }

                Console.WriteLine("### RECEIVED APPLICATION MESSAGE ###");
                Console.WriteLine($"+ Topic = {e.ApplicationMessage.Topic}");
                Console.WriteLine($"+ Payload = {payloadText}");
                Console.WriteLine($"+ QoS = {e.ApplicationMessage.QualityOfServiceLevel}");
                Console.WriteLine($"+ Retain = {e.ApplicationMessage.Retain}");
                Console.WriteLine();

                return CompletedTask.Instance;
            };

            client.ConnectedAsync += async _ =>
            {
                Console.WriteLine("### CONNECTED WITH SERVER ###");

                await client.SubscribeAsync("#");

                Console.WriteLine("### SUBSCRIBED ###");
            };

            client.DisconnectedAsync += async _ =>
            {
                Console.WriteLine("### DISCONNECTED FROM SERVER ###");
                await Task.Delay(TimeSpan.FromSeconds(5));

                try
                {
                    await client.ConnectAsync(clientOptions);
                }
                catch
                {
                    Console.WriteLine("### RECONNECTING FAILED ###");
                }
            };

            try
            {
                await client.ConnectAsync(clientOptions);
            }
            catch (Exception exception)
            {
                Console.WriteLine("### CONNECTING FAILED ###" + Environment.NewLine + exception);
            }

            Console.WriteLine("### WAITING FOR APPLICATION MESSAGES ###");

            while (true)
            {
                Console.ReadLine();

                await client.SubscribeAsync("test");

                var applicationMessage = new MqttApplicationMessageBuilder()
                    .WithTopic("A/B/C")
                    .WithPayload("Hello World")
                    .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce)
                    .Build();

                await client.PublishAsync(applicationMessage);
            }
        }
        catch (Exception exception)
        {
            Console.WriteLine(exception);
        }
    }
}